using System;
using System.Collections.Generic;
using System.Diagnostics;
using Mbs.Collections;

namespace Mbs.Modularity.AddIns
{ 
    [Serializable]
    [DebuggerTypeProxy(typeof(DebuggerEnumerableView<>))]
    internal class AddInItemCollection : IAddInItemCollection, ICloneable
    {
        private Dictionary<string, IAddInNode> InnerMap;
        private List<IAddInNode> Items;

        private static readonly object InnerLock = new object();

        public AddInItemCollection()
        {
            InnerMap = new Dictionary<string, IAddInNode>(StringComparer.OrdinalIgnoreCase);
            Items = new List<IAddInNode>();
        }

        public int Count
        {
            get { return Items.Count; }
        }


        public void Add(IAddInNode item)
        {
            Debug.Assert(item != null, "item == null");

            lock (InnerLock)
            {
                if (!Contains(item.Path))
                {
                    var oldBrother = item.Properties.Get<string>("OldBrother");
                    if (string.IsNullOrEmpty(oldBrother))
                        Items.Add(item);
                    else
                    {
                        var oldBrotherPath = item.ParentPath + "/" + oldBrother;
                        var index = Items.FindIndex((i) => i.Path == oldBrotherPath);
                        if (index != -1)
                            Items.Insert(index, item);
                        else
                            Items.Add(item);
                    }
                    InnerMap[item.Path] = item;
                }
            }
        }


        public void Remove(string path)
        {
            lock (InnerLock)
            {
                if (Contains(path))
                {
                    var item = InnerMap[path];
                    Items.Remove(item);
                    InnerMap.Remove(path);
                }
            }
        }

        public bool Contains(string path)
        {
            if (string.IsNullOrEmpty(path)) return false;

            return InnerMap.ContainsKey(path.Trim('/'));
        }

        object ICloneable.Clone()
        {
            return Clone();
        }

        public IAddInItemCollection Clone()
        {
            var o = new AddInItemCollection();
            if (Count > 0)
            {
                foreach (var item in Items.ToArray())
                    o.Add(item.Clone());
            }
            return o;
        }

        public IAddInNode this[string path]
        {
            get
            {
                lock (InnerLock)
                {
                    if (Contains(path))
                        return InnerMap[path];
                    return null;
                }
            }
        }

        public IEnumerator<IAddInNode> GetEnumerator()
        {
            return Items.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return Items.GetEnumerator();
        }
    }
}
